#!/bin/bash

SEQPIPE_DIR=.seqpipe
SEQPIPE_LOG=${SEQPIPE_DIR}/history.log

########################################

function do_show_cmd_line
{
	ID="$1"
	if [ -z "${ID}" ]; then
		# Without any options, show all records
		cat ${SEQPIPE_LOG}
	elif (echo ${ID} | grep -q -E "^[0-9]+(\.[0-9]+)+$") then
		# With an option of ID, show its record
		cat ${SEQPIPE_LOG} | awk '$1=="'${ID}'"'
	elif (echo ${ID} | grep -q -E "^[+-]?0+$") then
		# With option of digit '0', show all records
		cat ${SEQPIPE_LOG}
	elif (echo ${ID} | grep -qE "^\+?[0-9]+$") then
		# With positive integer (n), show the first n-th record
		head ${SEQPIPE_LOG} -n$(echo ${ID} | sed "s/^+//g") | tail -n1
	elif (echo ${ID} | grep -qE "^-[1-9]+$") then
		# With negative integer (n), show the last n-th record
		tail ${SEQPIPE_LOG} -n$(echo ${ID} | sed "s/^-//g") | head -n1
	else
		echo "Error: Invalid option '${ID}'!" >/dev/stderr
		exit 1
	fi
}

function do_list_log_files
{
	ID="$(do_show_cmd_line $* | tail -n1 | cut -f1)"
	if [ -d ${SEQPIPE_DIR}/${ID}/ ]; then
		cd ${SEQPIPE_DIR} && ls -l ${ID}/*
	elif [ -f ${SEQPIPE_DIR}/${ID}.tar.gz ]; then
		zcat ${SEQPIPE_DIR}/${ID}.tar.gz | tar tv
	else
		echo "Error: Missing log file for SeqPipe run '${ID}'!" >/dev/stderr
		exit 1
	fi
}

function do_cat_log_file
{
	FILE="$*"
	ID=$(echo ${FILE} | cut -d"/" -f1)
	FILE=$(echo ${FILE} | cut -d"/" -f2-)
	if [ "." == "${ID}" ]; then
		ID=$(echo ${FILE} | cut -d"/" -f1)
		FILE=$(echo ${FILE} | cut -d"/" -f2-)
	fi
	if [ -d ${SEQPIPE_DIR}/${ID}/ ]; then
		cat ${SEQPIPE_DIR}/${ID}/${FILE}
	elif [ -f ${SEQPIPE_DIR}/${ID}.tar.gz ]; then
		zcat ${SEQPIPE_DIR}/${ID}.tar.gz | tar x -O ${ID}/${FILE}
	else
		echo "Error: Missing log file for SeqPipe run '${ID}'!" >/dev/stderr
		exit 1
	fi
}

function do_show_log
{
	ID="$(do_show_cmd_line $* | tail -n1 | cut -f1)"
	do_cat_log_file ${ID}/log
}

function do_show_sysinfo
{
	ID="$(do_show_cmd_line $* | tail -n1 | cut -f1)"
	do_cat_log_file ${ID}/sysinfo
}

function do_show_shell_cmds
{
	do_show_log $* | grep -E "\[shell\]"
}

function do_remove_log
{
	ID=""
	FORCE=""
	while [ -n "$1" ]; do
		if [ "-f" == "$1" ]; then
			FORCE="-f"
		else
			ID="$1"
		fi
		shift
	done
	
	if [ -z "${ID}" ]; then
		echo "Usage: seqpipe.history remove <id>"
		exit 1
	fi
	if [ -z "$(cat ${SEQPIPE_LOG} | awk '$1=="'${ID}'"')" \
		-a ! -d ${SEQPIPE_DIR}/${ID}/ \
		-a ! -f ${SEQPIPE_DIR}/${ID}.tar.gz ]; then

		echo "ERROR: Can not find SeqPipe run for '${ID}'!" >/dev/stderr
		exit 1
	fi
	if [ -z "${FORCE}" ]; then
		if [ -z "$(do_show_log ${ID} | tail -n1 | grep -E 'Pipeline (finished|aborted)')" ]; then
			echo "WARNING: SeqPipe run '${ID}' may not finish or abnormally terminated!" >/dev/stderr
			echo "  You may add option '-f' to force to remove the record." >/dev/stderr
			exit 1
		fi
	fi

	if [ -z "${FORCE}" ]; then
		echo -n "Are you sure to remove seqpipe run '${ID}' (y/n)? "
		read C
		if [ "$(echo $C | cut -c1)" != "y" -a "$(echo $C | cut -c1)" != "Y" ]; then
			exit 1
		fi
	fi

	if [ "$(uname -s)" == "Darwin" ]; then
		SED_INLINE_OPT='-i ""'
	else
		SED_INLINE_OPT=-i
	fi

	N=$(grep -n "${ID}" ${SEQPIPE_LOG} | cut -d: -f1)
	if [ -n "${N}" ]; then
		if [ "$(uname -s)" == "Darwin" ]; then
			sed -i"" "${N}d" ${SEQPIPE_LOG}
		else
			sed -i "${N}d" ${SEQPIPE_LOG}
		fi
	fi
	rm -rf ${SEQPIPE_DIR}/${ID}{/,.tar.gz}
	echo "SeqPipe run '${ID}' has been removed successfully!"

	LAST=$(readlink ${SEQPIPE_DIR}/last)
	if [ "${ID}" == "${LAST}" -o "${ID}.tar.gz" == "${LAST}" ]; then
		ID=$(do_show_cmd_line | cut -f1 | tail -n1)
		if [ -z "${ID}" ]; then
			rm -f ${SEQPIPE_DIR}/last
		elif [ -d ${SEQPIPE_DIR}/${ID}/ ]; then
			ln -sf ${ID} ${SEQPIPE_DIR}/last
		elif [ -f ${SEQPIPE_DIR}/${ID}.tar.gz ]; then
			ln -sf ${ID}.tar.gz ${SEQPIPE_DIR}/last
		fi
	fi
}

function do_compress_log
{
	ID=""
	FORCE=""
	while [ -n "$1" ]; do
		if [ "-f" == "$1" ]; then
			FORCE="-f"
		else
			ID="$1"
		fi
		shift
	done
	
	if [ -z "${ID}" ]; then
		echo "Usage: seqpipe.history compress <id>"
		exit 1
	fi
	if [ -z "$(cat ${SEQPIPE_LOG} | awk '$1=="'${ID}'"')" ]; then
		echo "ERROR: Can not find SeqPipe run for '${ID}'!" >/dev/stderr
		exit 1
	fi
	if [ -d ${SEQPIPE_DIR}/${ID}/ ]; then
		if [ -z "${FORCE}" ]; then
			if [ -z "$(tail -n1 ${SEQPIPE_DIR}/${ID}/log | grep -E 'Pipeline (finished|aborted)')" ]; then
				echo "WARNING: SeqPipe run '${ID}' may not finish or abnormally terminated!" >/dev/stderr
				echo "  You may add option '-f' to force ${CMD} the record." >/dev/stderr
				exit 1
			fi
		fi

		tar c -C ${SEQPIPE_DIR} ${ID}/ | gzip -9c > ${SEQPIPE_DIR}/${ID}.tar.gz \
			&& rm -rf ${SEQPIPE_DIR}/${ID}/ \
			&& echo "SeqPipe run '${ID}' has been compressed successfully!"

		LAST=$(readlink ${SEQPIPE_DIR}/last)
		if [ "${ID}" == "${LAST}" ]; then
			ln -sf ${ID}.tar.gz ${SEQPIPE_DIR}/last
		fi
	fi
}

function do_compress_log_all
{
	do_show_cmd_line | cut -f1 | xargs -i seqpipe.history compress {} $*
}

function do_upgrade_log
{
	ls -F ${SEQPIPE_DIR} | grep -v '/' | egrep '^[0-9]+\.[0-9]+\..*$' | while read NAME; do
		DIR="$(echo "${NAME}" | cut -d'.' -f1-2)"
		FILE="$(echo "${NAME}" | cut -d'.' -f3-)"
		[ -d ${SEQPIPE_DIR}/${DIR} ] || mkdir -pv ${SEQPIPE_DIR}/${DIR}
		if [ -f ${SEQPIPE_DIR}/${DIR}/${FILE} ]; then
			echo "ERROR: File '${SEQPIPE_DIR}/${DIR}/${FILE}' has already existed!"
			exit 1
		fi
		mv -iv ${SEQPIPE_DIR}/${NAME} ${SEQPIPE_DIR}/${DIR}/${FILE}
	done
}

########################################

function show_usage
{
	echo "
Histroy Manipulator for SeqPipe (a SEQuencing data analsysis PIPEline framework)
Version: 0.1.0 (\$Rev: 354 $)
Author : Linlin Yan (yanll<at>mail.cbi.pku.edu.cn)
Copyright: 2012-2013, Centre for Bioinformatics, Peking University, China
Websites: http://seqpipe.googlecode.com
          http://www.cbi.pku.edu.cn

Usage: seqpipe.history <command> [<options>]

Support commands:
   show     [<id_or_order>]        # Show run id and command line
   log      [<id_or_order>]        # Show SeqPipe log of the run
   ls       [<id_or_order>]        # List log files of the run
   cat      [<file>]               # Cat the log file
   sysinfo  [<id_or_order>]        # Show sysinfo of the run
   cmd      [<id_or_order>]        # Show shell commands of the run
   remove   [-f] <id>              # Remove all log files of the run
   compress [-f] <id>              # Compress the run log files into .tar.gz
   compress_all [-f]
   upgrade                         # Upgrade log files from old version
   help"

	if [ "verbose" == "$1" ]; then
		echo "
Note:
   <id_or_order> could be:
       formated as \"<number>.<number>\", which represents ID of a SeqPipe run;
     or a positive integer, which means the first n-th record;
     or a negative integer, wihch means the last n-th record 
"
	else
		echo "
Use 'help' command to show more detail message.
"
	fi
}

########################################

if [ -z "$1" ]; then
	show_usage
	exit 1
elif [ "help" == "$1" ]; then
	show_usage "verbose"
	exit 1
fi

if [ ! -f ${SEQPIPE_LOG} ]; then
	echo "ERROR: Can not find history of seqpipe here!" >/dev/stderr
	exit 1
fi

CMD=$1
shift

if [ "${CMD}" == "show" ]; then
	do_show_cmd_line $*
elif [ "${CMD}" == "log" ]; then
	do_show_log $*
elif [ "${CMD}" == "ls" ]; then
	do_list_log_files $*
elif [ "${CMD}" == "cat" ]; then
	do_cat_log_file $*
elif [ "${CMD}" == "sysinfo" ]; then
	do_show_sysinfo $*
elif [ "${CMD}" == "cmd" ]; then
	do_show_shell_cmds $*
elif [ "${CMD}" == "remove" ]; then
	do_remove_log $*
elif [ "${CMD}" == "compress" ]; then
	do_compress_log $*
elif [ "${CMD}" == "compress_all" ]; then
	do_compress_log_all $*
elif [ "${CMD}" == "upgrade" ]; then
	do_upgrade_log
else
	echo "ERROR: Invalid command '${CMD}'!"
	exit 1
fi
exit 0
